home *** CD-ROM | disk | FTP | other *** search
- /*
- *
- * mac mail check network checking module
- * by Aaron Wohl (aw0g+@andrew.cmu.edu) jul 1990
- * Carnegie-Mellon University
- * Pittsburgh, PA 15213-3890
- * (412)-268-5032
- *
- */
-
- #include "MacTCPCommonTypes.h"
- #include "UDPPB.h"
- #include "gms.h"
- #include "mmc_core.h"
- #include "mmc_notify.h"
- #include "mmc_core_private.h"
- #include "mmc_config.h"
-
- #include <string.h>
-
- mmc_gl_t mmc_gl;
-
- /*
- * extended io pb with some of our variables on the end
- */
- struct xpb_R {
- union {
- ioParam iopb;
- UDPiopb pb;
- }x;
- void (*success_rtn)(struct xpb_R *pb); /*routines for when io finishes*/
- int state_name; /*MCE_ name of what we are trying to do*/
-
- };
- typedef struct xpb_R xpb,*xpb_pt;
-
- static struct {
- StreamPtr udp_stream; /*upd port*/
- xpb mainpb; /*used for all calls except release*/
- /*
- * declare a smaller than max gms_mail_status since we never send
- * real long usernames
- */
- long gms_send_space[(GMS_nameoffset+MMC_uname_len*2+12)/sizeof(long)];
- } ip_gl;
- #define GMS_send ((gms_mail_status_pt)(&ip_gl.gms_send_space))
-
- static void mmc_start(void);
- static void poll_server(void);
-
- /*
- * mactcp doesn't seem to allow a smaller buffer
- */
- #define UDP_BUF_SIZE (4000)
-
- /*
- * remember last error
- */
- LDEF(void set_error(int mce_kind,int syserrcode))
- {
- mmc_gl.cs.mmc_last_err_kind=mce_kind;
- mmc_gl.cs.mmc_last_err_syserr=syserrcode;
- if(mmc_gl.cps.ev[EV_error].ev_event!=mmc_note_new_error) {
- mmc_note_no_mail();
- set_event(EV_error,mmc_note_new_error,ERROR_ANNOUNCE_TIME);
- }
- }
-
- /*
- * an error that nukes the connection occured
- * to help in debugging and notifying the user
- */
- LDEF(void set_conn_err(int mce_kind,int syserrcode))
- {
- set_error(mce_kind,syserrcode);
- set_event(EV_retrans,mmc_start,RESTART_ON_ERROR_TIME);
- }
-
- /*
- * set the parts of a udp iopb that are
- * the same for all calls
- * note that PBOpen doesn't take a udp iopb
- */
- LDEF(void init_udp_pb(UDPiopb *pb,int code))
- {
- INIT_CPB(*pb,mmc_gl.cps.ip_ref,code);
- pb->udpStream = ip_gl.udp_stream;
- return;
- }
-
- /*
- * invalidate things that depend on current host
- */
- LDEF(void invalide_current_host(void))
- {
- mmc_gl.cps.change_count=0;
- }
-
- /*
- * close down, will auto restart if MMC_want_open
- */
- LDEF(void mmc_close(void))
- {
- UDPiopb pb;
- int err;
-
- /*
- * releasing the udp port below will abort any pending io
- * so don't leave the pending flag set
- */
- gTURN_OFF_FLAGS(MCS_io_pending);
- set_event(EV_retrans,mmc_start,RESTART_ON_ERROR_TIME);
- mmc_note_no_mail();
-
- if((mmc_gl.cps.ip_ref!=0)&&
- (ip_gl.udp_stream!=0)) {
- init_udp_pb(&pb,UDPRelease);
- pb.csParam.create.rcvBuff = mmc_gl.cps.udp_buf;
- pb.csParam.create.rcvBuffLen = UDP_BUF_SIZE;
-
- ip_gl.udp_stream=0; /*eithor way say we are done*/
- err=PBControl((void*)&pb,FALSE); /*do this syncronous, get it done*/
-
- if(err!=0)
- set_conn_err(MCE_UDP_REL,err);
- mmc_gl.cps.packet_waiting=0;
- }
-
- mmc_gl.cps.ip_ref=0; /*open the driver again if we gTURN on again*/
- }
-
- /*
- * close down, don't try to restart
- */
- LDEF(void mmc_shutdown(void))
- {
- strcpy(mmc_gl.cs.mmc_text_state,"MailChecking is shut off");
- mmc_close();
- set_event(EV_retrans,EV_NOTHING,0);
- }
-
- /*
- * set a perminante error that will shutdown
- * with no automatic retry
- */
- LDEF(void set_perm_error(int mce_kind,int syserrcode))
- {
- mmc_shutdown();
- set_conn_err(mce_kind,syserrcode);
- }
-
- void mmc_uninit(void)
- {
- mmc_shutdown();
- if(mmc_gl.cps.udp_buf!=0)
- DisposPtr(mmc_gl.cps.udp_buf);
- mmc_note_uninit();
- memset(&mmc_gl,0,sizeof(mmc_gl));
- memset(&ip_gl,0,sizeof(ip_gl));
- return;
- }
-
- /*
- * io failure handler/routines to close stream
- */
- LDEF(void mmc_io_fail(xpb_pt pb,int state))
- {
- gTURN_OFF_FLAGS(MCS_io_pending);
- mmc_close();
- set_conn_err(state,pb->x.pb.ioResult);
- }
-
- /*
- * see if a pb has finished
- */
- LDEF(void poll_pb(xpb_pt pb))
- {
- do {
- int done=pb->x.pb.ioResult;
- if(done==1) /*still running?*/
- return; /* yes*/
- gTURN_OFF_FLAGS(MCS_io_pending);
- if(done==0) {
- (*(pb->success_rtn))(pb);
- if(gFLSET(MCS_io_pending))
- continue;
- } else
- mmc_io_fail(pb,pb->state_name);
- } while(FALSE);
- }
-
- /*
- * wait for io to finish then enter a new state
- */
- LDEF(void finish_io(
- xpb_pt pb,
- int initial_result,
- void (*success_rtn)(),
- int description))
- {
- pb->success_rtn=success_rtn;
- pb->state_name=description;
- gTURN_ON_FLAGS(MCS_io_pending);
- if(initial_result<0)
- mmc_io_fail(pb,pb->state_name);
- else
- poll_pb(pb);
- }
-
- LDEF(void IOCompletionProc(struct UDPiopb *iopb))
- {
- }
-
- /*
- * do a macip async call
- */
- LDEF(void do_macip_async(
- xpb_pt pb,
- int code,
- void (*success_rtn)(),
- int description))
- {
- init_udp_pb(&pb->x.pb,code);
- pb->x.pb.ioCompletion=IOCompletionProc;
- finish_io(pb,PBControl((void*)pb,TRUE),success_rtn,description);
- }
-
- LDEF(void act_idle(xpb_pt pb))
- {
- }
-
- LDEF(update_ask_time(void))
- {
- int delay;
- delay=imax(ABS_MIN_POLL,mmc_gl.cps.server_poll);
- delay=imin(delay,ABS_MAX_POLL);
- set_event(EV_retrans,poll_server,POLL_TIME);
- mmc_gl.cps.unans_queries=0;
- }
-
- LDEF(void decode_recv(gms_mail_status_pt gm,char *new_text))
- {
- int ch0=((gm->gms_change_count0!=0)&&
- (mmc_gl.cps.change_count!=gm->gms_change_count0)&&
- (strcmp(mmc_gl.cs.mmc_text_state,new_text)!=0));
- int prev_flags=gm->gms_flags;
- long new_flags;
-
- mmc_gl.cps.change_count=gm->gms_change_count0;
- mmc_gl.cps.server_poll=
- imin(ABS_MAX_POLL,imax(gm->gms_poll_time,ABS_MIN_POLL));
- mmc_gl.cs.mmc_remind_time=
- imin(2*HOURS,imax(MIN_REMIND,mmc_gl.cs.mmc_remind_time));
-
- update_ask_time();
- strcpy(mmc_gl.cs.mmc_text_state,new_text);
-
- /*
- * if we know knothing is going on for certain,
- * don't give a spurious error as soon as the
- * the net flakes out
- */
- if((gm->gms_flags&gms_fl_error)!=0)
- set_error(MCE_REM_ERR,0);
- else {
- mmc_note_no_error();
- if((gm->gms_flags&gms_fl_mail)==0)
- mmc_note_no_mail();
- else if(ch0)
- mmc_note_new_mail();
- else
- mmc_note_old_mail();
- }
- }
-
- LDEF(void gms_read(mmc_read_result_pt rr))
- {
- long buf[(GMS_nameoffset+sizeof(long))/sizeof(long)];
- register gms_mail_status_pt gm= (gms_mail_status_pt)&buf;
- int text_len=rr->buf_size-GMS_nameoffset-1;
- char *new_text=rr->buf+GMS_nameoffset;
-
- if((rr->hostn!=HNUM0)&&
- (rr->hostn!=HNUM1)&&
- (rr->hostn!=deb_HNUM)) {
- mmc_gl.cps.last_rcv_error=1;
- return;
- }
-
- if(rr->portn!=MMW_port) {
- mmc_gl.cps.last_rcv_error=2;
- return;
- }
-
- if((rr->buf_size < (GMS_nameoffset+1))) {
- mmc_gl.cps.last_rcv_error=3;
- return;
- }
-
- mmc_gl.cps.unans_queries=0;
-
- /*
- * make a copy get proper alignment of longs
- */
- memcpy(gm,rr->buf,GMS_nameoffset);
-
- if(gm->gms_vers_maj!=GMS_VERS_MAJ) {
- set_perm_error(MCE_TOO_OLD,0);
- return;
- }
-
-
- if(rr->buf_size > GMS_max_size) {
- mmc_gl.cps.last_rcv_error=4;
- return;
- }
-
- if((*(rr->buf+rr->buf_size-1))!=0) {
- mmc_gl.cps.last_rcv_error=5;
- return;
- }
-
- if(strlen(new_text)!=(rr->buf_size-1-GMS_nameoffset)) {
- mmc_gl.cps.last_rcv_error=6;
- return;
- }
-
- if((*new_text)==0)
- strcpy(mmc_gl.cs.mmc_text_state,"[zero length message]");
-
- decode_recv(gm,new_text);
- }
-
- LDEF(void act_read_done(xpb_pt pb))
- {
- mmc_read_result rr;
-
- mmc_gl.cps.packet_waiting--;
-
- rr.buf=pb->x.pb.csParam.receive.rcvBuff;
- rr.buf_size=pb->x.pb.csParam.receive.rcvBuffLen;
- rr.portn=pb->x.pb.csParam.receive.remotePort;
- rr.hostn=pb->x.pb.csParam.receive.remoteHost;
-
- gms_read(&rr); /*process a read gms packet*/
-
- do_macip_async(pb,UDPBfrReturn,act_idle,MCE_UDP_REL);
- }
-
- LDEF(void act_read(xpb_pt pb))
- {
- memset(pb,0,(long)sizeof(*pb));
- pb->x.pb.csParam.receive.timeOut = 0; /*wait for a packet to come in forever*/
- pb->x.pb.csParam.receive.userDataPtr = (Ptr)&mmc_gl;
- do_macip_async(pb,UDPRead,act_read_done,MCE_UDP_READ);
- }
-
- /*
- * routine called when something happens to a udp port
- */
- LDEF(pascal void myUDPNotifyProc(
- StreamPtr udpStream,
- unsigned short eventCode,
- mmc_gl_t_pt agl,
- struct ICMPReport *icmpMsg))
- {
- if (eventCode==UDPDataArrival)
- agl->cps.packet_waiting++;
- }
-
- /*
- * make a stream
- */
- LDEF(mmc_open_mactcp(void))
- {
- xpb_pt pb=&ip_gl.mainpb;
- memset(pb,0,(long)sizeof(*pb));
- pb->x.iopb.ioNamePtr = (StringPtr)"\p.IPP";
- if((pb->x.pb.ioResult=PBOpen((void*)pb,FALSE))!=0) {
- mmc_io_fail(pb,MCE_MACTCP);
- return;
- }
- mmc_gl.cps.ip_ref=pb->x.iopb.ioRefNum;
-
- memset(pb,0,(long)sizeof(*pb));
- pb->x.pb.csParam.create.rcvBuff = mmc_gl.cps.udp_buf;
- pb->x.pb.csParam.create.rcvBuffLen = UDP_BUF_SIZE;
- pb->x.pb.csParam.create.notifyProc = (UDPNotifyProc)myUDPNotifyProc;
- pb->x.pb.csParam.create.userDataPtr = (Ptr)&mmc_gl;
- pb->x.pb.csParam.create.localPort=0;
- init_udp_pb(&pb->x.pb,UDPCreate);
- if((pb->x.pb.ioResult=PBControl((void*)pb,FALSE))!=0) {
- mmc_io_fail(pb,MCE_UDP_CREATE);
- return;
- }
-
- ip_gl.udp_stream=pb->x.pb.udpStream;
- set_event(EV_retrans,poll_server,0);
- }
-
- /*
- * open the mac ip driver
- */
- LDEF(void mmc_start(void))
- {
- if(ip_gl.udp_stream==0)
- mmc_open_mactcp();
- else
- set_event(EV_retrans,poll_server,0);
- }
-
- LDEF(void gms_send(xpb_pt pb))
- {
- static wdsEntry pentry[2];
- pentry[0].length=GMS_real_size(*GMS_send);
- pentry[0].ptr=(Ptr)GMS_send;
- pentry[1].length=0;
- pentry[1].ptr=0L;
- memset(pb,0,(long)sizeof(*pb));
- if(gFLSET(MCS_debug))
- pb->x.pb.csParam.send.remoteHost = deb_HNUM;
- else
- pb->x.pb.csParam.send.remoteHost = (mmc_gl.cps.cur_host)?HNUM0:HNUM1;
- pb->x.pb.csParam.send.remotePort = MMW_port;
- pb->x.pb.csParam.send.wdsPtr = (Ptr)&pentry;
- pb->x.pb.csParam.send.checkSum = TRUE;
- pb->x.pb.csParam.send.sendLength = pentry[0].length;
- do_macip_async(pb,UDPWrite,act_idle,MCE_UDP_WRITE);
- }
-
- /*
- * choose a server. perhaps the current one doesn't like us
- */
- LDEF(void pick_server(void))
- {
- if(mmc_gl.cps.unans_queries++ < NUM_FAST_RETRIES)
- return;
-
- mmc_note_no_mail();
- set_error(MCE_TIMEOUT,0);
-
- if((mmc_gl.cps.unans_queries%NUM_FAST_RETRIES)!=0)
- return;
-
- invalide_current_host();
-
- if((++mmc_gl.cps.cur_host)>=NUM_serv_hosts)
- mmc_gl.cps.cur_host=0;
- }
-
- /*
- * if it is time, ask the server
- */
- LDEF(void poll_server(void))
- {
- set_event(EV_retrans,poll_server,
- ((mmc_gl.cps.unans_queries>NUM_FAST_RETRIES)?POLL_TIME:RETRANS_MIN_TIME));
- pick_server();
-
- GMS_send->gms_vers_maj=GMS_VERS_MAJ;
- GMS_send->gms_vers_min=GMS_VERS_MIN;
- GMS_send->gms_type=gms_ask_mail;
- GMS_send->gms_id=mmc_gl.cps.seq_no++;
- GMS_send->gms_poll_time=POLL_TIME;
- strcpy(GMS_send->gms_text_buf,mmc_gl.cs.mmc_uname);
-
- gms_send(&ip_gl.mainpb);
- }
-
- /*
- * set text to ask server
- * returns TRUE if no valid text found
- */
- LDEF(void set_poll_name(mmc_state_pt s))
- {
- int len=imin(MMC_uname_len-1,imax(0,strlen(s->mmc_uname)));
-
- if(memcmp(mmc_gl.cs.mmc_uname,s->mmc_uname,len+1)!=0)
- mmc_gl.cps.change_count=0;
-
- memcpy(mmc_gl.cs.mmc_uname,s->mmc_uname,len);
- mmc_gl.cs.mmc_uname[len]=0;
- }
-
- LDEF(void update_flags(long new_flags))
- {
- long old_flags=mmc_gl.cs.mmc_st;
- mmc_gl.cs.mmc_st^=((old_flags^new_flags)&MCS_setable);
- /*
- * if no notification method is choosen
- * default to posting a message
- */
- if(!gFLSET(MCS_nblink))
- gTURN_ON_FLAGS(MCS_npost);
- }
-
- /*
- * initialize the world called from driver open routine
- * return an os error code to not open
- */
- int mmc_init()
- {
- if(mmc_gl.cps.udp_buf!=0) /*already initialized*/
- return 0;
- mmc_gl.cps.cur_host=TickCount()&1L;
- mmc_note_init();
- mmc_gl.cs.mmc_st_maj_ver=MMC_ST_maj_ver;
- mmc_gl.cs.mmc_st_min_ver=MMC_ST_min_ver;
- if((mmc_gl.cps.udp_buf=NewPtrSys(UDP_BUF_SIZE))==0)
- return MMCE_noopen;
- return 0;
- }
-
- /*
- * change the driver state call
- */
- int mmc_set_state(s)
- mmc_state_pt s;
- {
- int starting_up;
- if(s->mmc_st_maj_ver!=MMC_ST_maj_ver)
- return MMCE_bad_maj;
- if(mmc_gl.cps.udp_buf==0)
- return MMCE_noopen;
-
- update_flags(s->mmc_st);
- mmc_gl.cs.mmc_check_num=s->mmc_check_num;
-
- mmc_gl.cs.mmc_remind_time=
- imin(2*HOURS,imax(MIN_REMIND,s->mmc_remind_time));
-
- set_poll_name(s);
- mmc_note_no_mail();
-
- strcpy(mmc_gl.cs.mmc_text_state,"New MailCheck configuration set");
-
- if((!gFLSET(MCS_want_open))||(mmc_gl.cs.mmc_uname[0]==0)||(FLSET(*s,MCS_snooze))) {
- mmc_shutdown(); /*set text state on shutdown*/
- mmc_note_done();
- } else
- set_event(EV_retrans,mmc_start,0);
-
- if(FLSET(*s,MCS_snooze)) {
- mmc_note_no_error();
- strcpy(mmc_gl.cs.mmc_text_state,"45 min nap in progress");
- set_event(EV_retrans,mmc_start,SNOOZE_TIME);
- } else
- mmc_note_sound_init(s->mmc_sound_id);
-
- return 0;
- }
-
- /*
- * convert an unsigned number to text
- */
- static char *strunum(char *dst,long num);
- static char *strunum(dst,num)
- register char *dst;
- register long num;
- {
- register long rem;
- rem= num%10;
- num/=10;
- if(num!=0)
- dst=strunum(dst,num);
- *dst++ = '0'+rem;
- *dst=0;
- return dst;
- }
-
- /*
- * convert a signed number to text
- */
- static void strnum(char *dst,long num);
- static void strnum(dst,num)
- register char *dst;
- register long num;
- {
- if(num<0) {
- *dst++='-';
- num= -num;
- }
- strunum(dst,num);
- }
-
- /*
- * convert a system error number to human readable text
- */
- LDEF(void textify_syserr(char *dst,int ernum))
- {
- switch(ernum) {
- case 0: /*not really an error*/
- return;
- case -43:
- strcpy(dst,"The MacTCP driver does not seem to be installed.");
- return;
- case -23004:
- strcpy(dst,
- "A gateway is down or MacTCP isn't installed properly. If problem persists seek assistance.");
- break;
- case -23015:
- strcpy(dst,
- "The server host is up but it isn't running a MacCheck server.");
- break;
- case -23012:
- strcpy(dst,
- "The MacCheck server is not responding. Perhaps a gateway just went down.");
- break;
- default:
- strcpy(dst,
- "Mac OS error code ");
- strnum(dst+strlen(dst),ernum);
- }
- }
-
- /*
- * set mmc_text state to have the text of the current error
- */
- void textify_error(void)
- {
- switch(mmc_gl.cs.mmc_last_err_kind) {
- case MCE_NOERRR:
- return;
- case MCE_UDP_REL:
- strcpy(mmc_gl.cs.mmc_text_state,"UDP dispose");
- break;
- case MCE_TOO_OLD:
- strcpy(mmc_gl.cs.mmc_text_state,"MailCheck version too old to talk to server");
- return;
- break;
- case MCE_UDP_READ:
- strcpy(mmc_gl.cs.mmc_text_state,"UDP read");
- break;
- case MCE_UDP_CREATE:
- strcpy(mmc_gl.cs.mmc_text_state,"UDP create");
- break;
- case MCE_MACTCP:
- strcpy(mmc_gl.cs.mmc_text_state,"MacTCP open");
- break;
- case MCE_UDP_WRITE:
- strcpy(mmc_gl.cs.mmc_text_state,"UDP write");
- break;
- case MCE_REM_ERR:
- return;
- case MCE_TIMEOUT:
- strcpy(mmc_gl.cs.mmc_text_state,"MailCheck server does not respond");
- return;
- default:
- strcpy(mmc_gl.cs.mmc_text_state,"Undefined internal error");
- return;
- break;
- }
- strcat(mmc_gl.cs.mmc_text_state," failed. ");
- textify_syserr(mmc_gl.cs.mmc_text_state+strlen(mmc_gl.cs.mmc_text_state),mmc_gl.cs.mmc_last_err_syserr);
- }
-
- /*
- * set a little bit of state, namely that macmail is running
- */
- int mmc_setmmuser(mmc_state_pt s,mmc_priv_state_pt *active_priv_state)
- {
- int err;
- long want_snooze= s->mmc_st&MCS_snooze;
- char new_user[MMC_uname_len];
- memcpy(new_user,s->mmc_uname,MMC_uname_len);
- if((err=mmc_get_state(s,active_priv_state)!=0))
- return err;
- s->mmc_st^= (s->mmc_st^want_snooze)&MCS_snooze; /*set snooze accordingly*/
- if((new_user[0]!=0)&&(gFLSET(MCS_hearmm)))
- memcpy(s->mmc_uname,new_user,MMC_uname_len);
- if((err=mmc_set_state(s))!=0)
- return err;
- return mmc_get_state(s,active_priv_state);
- }
-
- /*
- * return current state
- */
- int mmc_get_state(old_state,active_priv_state)
- mmc_state_pt old_state;
- mmc_priv_state_pt *active_priv_state;
- {
- if(old_state->mmc_st_maj_ver!=MMC_ST_maj_ver)
- return MMCE_bad_maj;
- textify_error();
- *old_state=mmc_gl.cs;
- if(mmc_gl.cs.mmc_last_err_kind==MCE_NOERRR)
- old_state->mmc_st&= ~MCS_error;
- else
- old_state->mmc_st|= MCS_error;
- *active_priv_state= &mmc_gl.cps;
- return 0;
- }
-
- /*
- * mmc_tick - called periodicly to keep us happy
- */
- void mmc_tick()
- {
- if(mmc_gl.cps.udp_buf==0)
- return;
- if (gFLSET(MCS_io_pending))
- poll_pb(&ip_gl.mainpb);
- if(ip_gl.udp_stream!=0)
- if ((!gFLSET(MCS_io_pending)) &&
- (mmc_gl.cps.packet_waiting!=0))
- act_read(&ip_gl.mainpb);
-
- {
- register long now=TickCount();
- register int i;
- register mmc_event_pt ev= &mmc_gl.cps.ev[0];
- for(i=0;(i<EV_NUM)&& !gFLSET(MCS_io_pending);i++,ev++)
- if((now>=ev->ev_time)&&
- (ev->ev_event!=0)) {
- void (*the_event)(void)=ev->ev_event;
- ev->ev_event=0;
- (*(the_event))();
- }
- }
- }
-
-